package com.easylinkin.linkappapi.intelligentrule.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.bases.redis.util.RedisUtil;
import com.easylinkin.linkappapi.common.utils.ExpressionUtil;
import com.easylinkin.linkappapi.device.entity.Device;
import com.easylinkin.linkappapi.deviceattribute.constant.PhysicalModelTypeConstant;
import com.easylinkin.linkappapi.deviceattribute.entity.DeviceAttribute;
import com.easylinkin.linkappapi.deviceattributestatus.entity.DeviceAttributeStatus;
import com.easylinkin.linkappapi.intelligentrule.entity.IntelligentRuleExpression;
import com.easylinkin.linkappapi.intelligentrule.mapper.IntelligentRuleExpressionMapper;
import com.easylinkin.linkappapi.intelligentrule.service.IntelligentRuleExpressionService;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.easylinkin.linkappapi.ruleengine.entity.RuleTrigger;
import com.easylinkin.linkappapi.ruleengine.service.RuleTriggerService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Tongjie
 * @since 2020-05-16
 */
@Service
public class IntelligentRuleExpressionServiceImpl extends ServiceImpl<IntelligentRuleExpressionMapper, IntelligentRuleExpression> implements IntelligentRuleExpressionService {

    @Resource
    private RedisUtil redisUtil;
    @Resource
    private RuleTriggerService ruleTriggerService;


    /**
     * 日志记录对象
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(IntelligentRuleExpressionServiceImpl.class);

    @Override
    public void deleteForceByIds(List<String> ids) {
        if (!CollectionUtils.isEmpty(ids)) {
            baseMapper.deleteForceByIds(ids);
        }
    }


    @Override
    public boolean checkMeetExpressions(Device device, List<IntelligentRuleExpression> intelligentRuleExpressionList) {

        if (CollectionUtils.isEmpty(intelligentRuleExpressionList)) {
            LOGGER.info("无相应规则表达式");
            return true;
        }

        intelligentRuleExpressionList.sort((a, b) -> {
            if (a.getSortNo() == null || b.getSortNo() == null) {
                return 0;
            }
            if (a.getSortNo() > b.getSortNo()) {
                return 1;
            } else if (a.getSortNo().equals(b.getSortNo())) {
                return 0;
            } else {
                return -1;
            }
        });

        IntelligentRuleExpression intelligentRuleExpression0 = intelligentRuleExpressionList.get(0);
//        逻辑运算符会跟着上一条  最后一条将为空

        List<DeviceAttributeStatus> deviceAttributeStatusList = device.getDeviceAttributeStatusList();
        Assert.notEmpty(deviceAttributeStatusList, "设备属性状态为空");

//        检查设备状态不正常，默认false
        boolean isMeetCondition = false;

//        兼容以前  逻辑运算符跟着下一条的情况（以前是: 第一条的逻辑运算符为空）
        if (ObjectUtils.isEmpty(intelligentRuleExpression0.getLogicCode())) {
            for (IntelligentRuleExpression intelligentRuleExpression : intelligentRuleExpressionList) {
                if ("||".equals(intelligentRuleExpression.getLogicCode()) && isMeetCondition) {
                    return true;
                }
                if ("&&".equals(intelligentRuleExpression.getLogicCode()) && !isMeetCondition) {
                    return false;
                }
                Assert.notNull(intelligentRuleExpression.getDeviceAttribute(), "规则表达式对应属性id查到属性为空");
                isMeetCondition = getSingleCheckFromDeviceAttributeStatusListByAttrIdentifier(intelligentRuleExpression, deviceAttributeStatusList);
            }
        } else {
            for (IntelligentRuleExpression intelligentRuleExpression : intelligentRuleExpressionList) {
                Assert.notNull(intelligentRuleExpression.getDeviceAttribute(), "规则表达式对应属性id查到属性为空");
                isMeetCondition = getSingleCheckFromDeviceAttributeStatusListByAttrIdentifier(intelligentRuleExpression, deviceAttributeStatusList);
                if (isMeetCondition && "||".equals(intelligentRuleExpression.getLogicCode())) {
                    return true;
                }
                if (!isMeetCondition && "&&".equals(intelligentRuleExpression.getLogicCode())) {
                    return false;
                }
            }
        }

        if (!isMeetCondition) {
            LOGGER.info("校验不满足智能规则表达式条件，方法将提前结束");
        }
        if (isMeetCondition) {
            StringBuffer sb = new StringBuffer();
//        如果满足条件，将设备过来的报文中筛选包含触发器中字段的设备属性，并将其放入缓存备用，产生告警时候取其值随告警工单一起插入表
            for (IntelligentRuleExpression intelligentRuleExpression : intelligentRuleExpressionList) {
                for (DeviceAttributeStatus deviceAttributeStatus : deviceAttributeStatusList) {
                    DeviceAttribute attr = intelligentRuleExpression.getDeviceAttribute();
                    if (attr != null && attr.getIdentifier().equals(deviceAttributeStatus.getPropCode())) {
                        sb.append(deviceAttributeStatus.getPropName()).append(":");
                        String propVal = deviceAttributeStatus.getPropValue();
                        if ("enum".equals(attr.getUnit()) || "bool".equals(attr.getUnit())) {
                            String json = attr.getSpecs();
                            if (json != null) {
                                try {
                                    JSONObject jsonObj = JSONObject.parseObject(json);
                                    Object obj = jsonObj.get(deviceAttributeStatus.getPropValue());
                                    if (obj != null) {
                                        propVal = obj.toString();
                                    }
                                } catch (Exception e) {
                                    LOGGER.info("设备属性解析说明，查询属性名称失败:{}", e.getMessage());
                                }
                            }
                        }
                        sb.append(propVal).append(",");
                    }
                }
            }
            RuleTrigger rt = ruleTriggerService.getById(intelligentRuleExpression0.getRuleTriggerId());
            if (rt != null && StringUtils.isNotEmpty(rt.getRuleEngineId()) && sb.length() > 1) {
                redisUtil.set(rt.getRuleEngineId() + "@" + device.getCode(), sb.substring(0, sb.length() - 1), 600);
            }
        }

        return isMeetCondition;
    }

    /**
     * 当设备没有属性时返回为false
     * */
    @Override
    public boolean checkPropertyForMonitor(Device device, List<IntelligentRuleExpression> intelligentRuleExpressionList) {

        if (CollectionUtils.isEmpty(intelligentRuleExpressionList)) {
            LOGGER.info("无相应规则表达式");
            return true;
        }

        intelligentRuleExpressionList.sort((a, b) -> {
            if (a.getSortNo() == null || b.getSortNo() == null) {
                return 0;
            }
            if (a.getSortNo() > b.getSortNo()) {
                return 1;
            } else if (a.getSortNo().equals(b.getSortNo())) {
                return 0;
            } else {
                return -1;
            }
        });

        IntelligentRuleExpression intelligentRuleExpression0 = intelligentRuleExpressionList.get(0);
//        逻辑运算符会跟着上一条  最后一条将为空

        List<DeviceAttributeStatus> deviceAttributeStatusList = device.getDeviceAttributeStatusList();
        if (deviceAttributeStatusList == null || deviceAttributeStatusList.isEmpty()) {
            return false;
        }

//        检查设备状态不正常，默认false
        boolean isMeetCondition = false;

//        兼容以前  逻辑运算符跟着下一条的情况（以前是: 第一条的逻辑运算符为空）
        if (ObjectUtils.isEmpty(intelligentRuleExpression0.getLogicCode())) {
            for (IntelligentRuleExpression intelligentRuleExpression : intelligentRuleExpressionList) {
                if ("||".equals(intelligentRuleExpression.getLogicCode()) && isMeetCondition) {
                    return true;
                }
                if ("&&".equals(intelligentRuleExpression.getLogicCode()) && !isMeetCondition) {
                    return false;
                }
                Assert.notNull(intelligentRuleExpression.getDeviceAttribute(), "规则表达式对应属性id查到属性为空");
                isMeetCondition = getSingleCheckFromDeviceAttributeStatusListByAttrIdentifier(intelligentRuleExpression, deviceAttributeStatusList);
            }
        } else {
            for (IntelligentRuleExpression intelligentRuleExpression : intelligentRuleExpressionList) {
                Assert.notNull(intelligentRuleExpression.getDeviceAttribute(), "规则表达式对应属性id查到属性为空");
                isMeetCondition = getSingleCheckFromDeviceAttributeStatusListByAttrIdentifier(intelligentRuleExpression, deviceAttributeStatusList);
                if (isMeetCondition && "||".equals(intelligentRuleExpression.getLogicCode())) {
                    return true;
                }
                if (!isMeetCondition && "&&".equals(intelligentRuleExpression.getLogicCode())) {
                    return false;
                }
            }
        }

        if (!isMeetCondition) {
            LOGGER.info("校验不满足智能规则表达式条件，方法将提前结束");
        }

        return isMeetCondition;
    }


    /**
     * 从设备属性状态中获取属性的值 判断单条属性判断结果值
     */
    private boolean getSingleCheckFromDeviceAttributeStatusListByAttrIdentifier(IntelligentRuleExpression intelligentRuleExpression, List<DeviceAttributeStatus> deviceAttributeStatusList) {
        DeviceAttribute deviceAttribute = intelligentRuleExpression.getDeviceAttribute();
        boolean isMeetCondition = false;
        String deviceAttributeStatusValue;
        if (PhysicalModelTypeConstant.ARRAY_OBJECT.equals(deviceAttribute.getParentUnit())) {

            DeviceAttributeStatus deviceAttributeStatus = deviceAttributeStatusList.stream().filter(e -> deviceAttribute.getParentPropCode().equals(e.getPropCode())).findFirst().orElse(null);
            List<Map<String, Object>> children = JSONObject.parseObject(deviceAttributeStatus.getPropValue(), List.class);
            List<Object> values = children.stream().map(e -> e.get(deviceAttribute.getIdentifier())).collect(Collectors.toList());
            for (Object value : values) {
                isMeetCondition = ExpressionUtil.checkExpressionMeet(deviceAttribute.getUnit(), value.toString(), intelligentRuleExpression.getCalculateSign(), intelligentRuleExpression.getValue());
                if (isMeetCondition) {
                    return isMeetCondition;
                }
            }

        } else if (PhysicalModelTypeConstant.OBJECT.equals(deviceAttribute.getParentUnit())) {

            DeviceAttributeStatus deviceAttributeStatus = deviceAttributeStatusList.stream().filter(e -> deviceAttribute.getParentPropCode().equals(e.getPropCode())).findFirst().orElse(null);
            Map<String, Object> objectMap = JSONObject.parseObject(deviceAttributeStatus.getPropValue(), Map.class);
            isMeetCondition = ExpressionUtil.checkExpressionMeet(deviceAttribute.getUnit(), objectMap.get(deviceAttribute.getIdentifier()).toString(), intelligentRuleExpression.getCalculateSign(), intelligentRuleExpression.getValue());
        } else if (PhysicalModelTypeConstant.ARRAY_SIMPLE.equals(deviceAttribute.getUnit())) {

            DeviceAttributeStatus deviceAttributeStatus = deviceAttributeStatusList.stream().filter(e -> deviceAttribute.getIdentifier().equals(e.getPropCode())).findFirst().orElse(null);
            List<Object> values = JSONObject.parseObject(deviceAttributeStatus.getPropValue(), List.class);
            for (Object value : values) {
                isMeetCondition = ExpressionUtil.checkExpressionMeet(deviceAttribute.getUnit(), value.toString(), intelligentRuleExpression.getCalculateSign(), intelligentRuleExpression.getValue());


                if (isMeetCondition) {
                    return isMeetCondition;
                }
            }
        } else {
            DeviceAttributeStatus deviceAttributeStatus = deviceAttributeStatusList.stream().filter(e -> deviceAttribute.getIdentifier().equals(e.getPropCode())).findFirst().orElse(null);
            deviceAttributeStatusValue = deviceAttributeStatus != null ? deviceAttributeStatus.getPropValue() : null;
            if (ObjectUtils.isEmpty(deviceAttributeStatusValue)) {
                return false;
            }
            String dataType = deviceAttribute.getUnit();
            String before = deviceAttributeStatusValue;
            String calculateSign = intelligentRuleExpression.getCalculateSign();
            String after = intelligentRuleExpression.getValue();
            isMeetCondition = ExpressionUtil.checkExpressionMeet(dataType, before, calculateSign, after);
        }
        return isMeetCondition;
    }

   
}
